package com.nhc.database.manager;

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.Point;

import com.astrob.activitys.AppContext;
import com.astrob.model.LonLat;
import com.astrob.naviframe.Start;
import com.astrob.util.Utils;
import com.astrob.view.MapViewS;
import com.astrob.view.TrackShow;
import com.nhc.database.dbmodel.Measure;
import com.nhc.database.dbmodel.MeasurePoint;
import com.nhc.database.greendao.MeasureDao;
import com.nhc.database.greendao.MeasurePointDao;

import org.greenrobot.greendao.database.Database;


import org.mapsforge.core.graphics.Style;
import org.mapsforge.core.util.MercatorProjection;
import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
import org.mapsforge.map.model.DisplayModel;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.util.TileSystem;
import org.osmdroid.views.MapView;
import org.osmdroid.views.Projection;
import org.osmdroid.views.overlay.Polyline;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;


public class MeasureCenter {

    private static MeasureCenter instance = new MeasureCenter();

    public static MeasureCenter getInstance() {
        return instance;
    }

    public void init() {

    }

    public Measure measureRT = null;//实时测量-- 测量点放在内存

    public Measure measureEdit = null;//编辑的测量
    //测量列表
    private ArrayList<Measure> measureList = new ArrayList<Measure>();

    //测量
    public void doQueryMeasure() {
        MeasureDao measureDao = AppContext.getInstances().getDaoSession().getMeasureDao();
        try {
            measureList = (ArrayList) measureDao.queryBuilder()
                    .where(MeasureDao.Properties.Id.notEq(0))
                    .orderAsc(MeasureDao.Properties.Id)
                    .build().list();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (measureList == null) {
            measureList = new ArrayList<Measure>();
        }
    }

    public void doDeleteAllMeasure() {
        if (measureList == null || measureList.size() < 1) {
            return;
        }

        ArrayList<Long> pkIds = new ArrayList<Long>();
        for (Measure measure : measureList) {
            pkIds.add(measure.getId());
        }

        MeasureDao measureDao = AppContext.getInstances().getDaoSession().getMeasureDao();
        doDeleteMeasure(pkIds);
    }

    public void doDeleteMeasure(ArrayList<Long> pkIds) {
        if (pkIds != null && pkIds.size() > 0) {
            MeasureDao measureDao = AppContext.getInstances().getDaoSession().getMeasureDao();
            measureDao.deleteByKeyInTx(pkIds);

            //删除测量上的点  ---执行SQL---
            String strMeasureIds = "";
            for (int i = 0; i < pkIds.size(); i++) {
                if (i == 0) {
                    strMeasureIds += pkIds.get(i) + "";
                } else {
                    strMeasureIds += "," + pkIds.get(i);
                }
            }
            removeMeasurePoints(strMeasureIds);

            //重新查询测量
            doQueryMeasure();
        }
    }

    //清空测量上的点
    public void removeMeasurePoints(String strMeasureIds) {
        if (strMeasureIds == null || strMeasureIds.length() < 1) {
            return;
        }
        MeasurePointDao measurePointDao = AppContext.getInstances().getDaoSession().getMeasurePointDao();
        try {
            String deletesql = "DELETE FROM MEASURE_POINT WHERE MEASURE_ID IN (" + strMeasureIds + ");";
            measurePointDao.getDatabase().execSQL(deletesql);
        } catch (SQLException e) {
            return;
        }

    }

    public final static Comparator<Measure> measureFunc0 = new Comparator<Measure>() {
        @Override
        public int compare(Measure object1, Measure object2) {
            return (int) (object1.getId() - object2.getId());
        }
    };


    //获取测量上的点(非正确顺序)
    public ArrayList<MeasurePoint> getMeasurePointListByMeasureId(Long measureId) {
        ArrayList<MeasurePoint> wpList = new ArrayList<MeasurePoint>();
        MeasurePointDao measurePointDao = AppContext.getInstances().getDaoSession().getMeasurePointDao();
        try {
            //此方法有问题，能查询到两个一样的MeasurePoint，不能输出两个id不同的MeasurePoint
            wpList = (ArrayList) measurePointDao.queryBuilder()
                    .where(MeasurePointDao.Properties.Measure_id.eq(measureId))
                    .orderAsc(MeasurePointDao.Properties.Id)
                    .build().list();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return wpList;
    }

    public Measure getMeasureById(long id) {
        if (measureList == null) {
            return null;
        }

        for (Measure measure : measureList) {
            if (measure.getId() == id) {
                return measure;
            }
        }
        return null;
    }

    public Long addNewMeasure() {
        String name = "001";
        MeasureDao measureDao = AppContext.getInstances().getDaoSession().getMeasureDao();
        try {
            Database db = measureDao.getDatabase();
            Cursor cursor = db.rawQuery("SELECT MAX(_id) FROM MEASURE ", null);
            while (cursor.moveToNext()) {
                Long id = cursor.getLong(0) + 1;
                name = new DecimalFormat("000").format(id);
                break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return saveMeasure(new Measure("测量" + name));
    }

    public Long saveMeasure(Measure measure) {
        if (measure == null) {
            return 0L;
        }

        MeasureDao measureDao = AppContext.getInstances().getDaoSession().getMeasureDao();
        long id = measureDao.insertOrReplace(measure);
        doQueryMeasure();

        return id;
    }

    public Long saveMeasurePoint(MeasurePoint measurePoint) {
        if (measurePoint == null) {
            return 0L;
        }
        MeasurePointDao measurePointDao = AppContext.getInstances().getDaoSession().getMeasurePointDao();

        long id = measurePointDao.insertOrReplace(measurePoint);
        measurePoint.setId(id);

        return id;
    }


    public ArrayList<Measure> getMeasureList() {
        return measureList;
    }

    public void setMeasureList(ArrayList<Measure> measureList) {
        this.measureList = measureList;
    }

    public void drawmeasureRT(Context context, Canvas canvas, float ws, MapViewS mapView) {
        if (measureRT == null || mapView == null
                || measureRT.measurePtList == null
                || measureRT.measurePtList.size() < 2) {
            return;
        }

        int w = mapView._mapWidth;
        int h = mapView._mapHeight;

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(6);
        paint.setAntiAlias(true);
        PathEffect pathEffect = new DashPathEffect(new float[]{5, 0}, 0);
        paint.setPathEffect(pathEffect);
        Path path = new Path();

        int step = getStep();
        int count = measureRT.measurePtList.size();
        paint.setColor(Color.parseColor("#AAFF0000"));

        Point AA = null;
        int ii = -1;
        for (int i = step; i < count; i += step) {
            LonLat poiLLA = measureRT.measurePtList.get(i - step).getLL();
            LonLat poiLLB = measureRT.measurePtList.get(i).getLL();

            poiLLA = Utils.wgs84togcj02(poiLLA.GetLon(), poiLLA.GetLat());//Utils GPS to 火星坐标
            poiLLB = Utils.wgs84togcj02(poiLLB.GetLon(), poiLLB.GetLat());//Utils GPS to 火星坐标

            double[] lineLL = {poiLLA.GetLon(), poiLLA.GetLat(), poiLLB.GetLon(), poiLLB.GetLat()};
            if (!Utils.isLineIntersectRectangle(mapView.getMapRegion(), lineLL)) {
                continue;
            }

            Point A = null;
            if (AA != null && ii == i - 1) {
                A = AA;
            } else {
                A = Start.getInstance().MapKit().LL2XY(poiLLA);//耗时操作能省则省
            }
            Point B = Start.getInstance().MapKit().LL2XY(poiLLB);
            AA = B;
            ii = i;

            int[] line = {A.x, A.y, B.x, B.y};
            if (Utils.revisePt(line, w, h)) {
                path.moveTo(line[0] * ws, line[1] * ws);
                path.lineTo(line[2] * ws, line[3] * ws);
            }
        }
        canvas.drawPath(path, paint);

        //画起点
        if (count > 0) {
            paint.setStyle(Paint.Style.FILL);
            paint.setTextSize(13);
            paint.setFakeBoldText(true);
            LonLat poiLL = measureRT.measurePtList.get(0).getLL();

            poiLL = Utils.wgs84togcj02(poiLL.GetLon(), poiLL.GetLat());//Utils GPS to 火星坐标

            if (mapView.isInMapRegion(poiLL)) {
                Point ff = Start.getInstance().MapKit().LL2XY(poiLL);
                paint.setColor(Color.parseColor("#AAAF0000"));
                canvas.drawCircle(ff.x * ws, ff.y * ws, Utils.dip2px(context, 12), paint);
                String strPrn = "S";
                float textWidth = paint.measureText(strPrn) / 2;
                float textHeight = paint.getTextSize() / 2;
                paint.setColor(Color.WHITE);
                canvas.drawText(strPrn, ff.x * ws - textWidth, ff.y * ws + textHeight - 1,
                        paint);
            }
        }
    }

    private int getStep() {
        double scale = Start.getInstance().MapKit().getScale();
        int step = 1;

        if (scale >= 300000) {
            step = 1;//10米比例尺，间隔5米
        } else if (scale >= 200000) {
            step = 2;//25米比例尺，间隔10米
        } else if (scale >= 100000) {
            step = 4;//50米比例尺，间隔20米
        } else if (scale >= 50000) {
            step = 8;//100米比例尺，间隔40米
        } else if (scale >= 250000) {
            step = 16;
        } else if (scale >= 10000) {
            step = 40;
        } else if (scale >= 5000) {
            step = 80;
        } else if (scale >= 2500) {
            step = 160;
        } else if (scale >= 1000) {
            step = 400;
        } else if (scale >= 500) {
            step = 800;
        } else if (scale >= 250) {
            step = 1600;
        } else {
            step = 3000;
        }
        return step;
    }

    public void drawmeasureRT2(Context context, Canvas canvas, MapView mapView, boolean isgcj02) {
        if (measureRT == null || mapView == null
                || measureRT.measurePtList == null
                || measureRT.measurePtList.size() < 2) {
            return;
        }

        int w = mapView.getWidth();
        int h = mapView.getHeight();

        BoundingBox bb = mapView.getBoundingBox();//获取当前区域
        double[] regions = {bb.getLonEast(), bb.getLatNorth(), bb.getLonWest(), bb.getLatSouth()};

        Polyline routeline = new Polyline();

        Paint paint = routeline.getPaint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(6);
        paint.setAntiAlias(true);
        PathEffect pathEffect = new DashPathEffect(new float[]{5, 0}, 0);
        paint.setPathEffect(pathEffect);

        int count = measureRT.measurePtList.size();
        paint.setColor(Color.parseColor("#AAFF0000"));

        List<GeoPoint> points = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            LonLat poiLL = measureRT.measurePtList.get(i).getLL();
            if (isgcj02) {
                poiLL = Utils.wgs84togcj02(poiLL.GetLon(), poiLL.GetLat());//Utils GPS to 火星坐标
            }
            points.add(new GeoPoint(poiLL.GetLat(), poiLL.GetLon()));
        }

        routeline.setPoints(points);
        routeline.draw(canvas, mapView, false);

        //画起点
        if (count > 0) {
            paint.setStyle(Paint.Style.FILL);
            paint.setTextSize(13);
            paint.setFakeBoldText(true);
            LonLat poiLL = measureRT.measurePtList.get(0).getLL();
            if (isgcj02) {
                poiLL = Utils.wgs84togcj02(poiLL.GetLon(), poiLL.GetLat());//Utils GPS to 火星坐标
            }

            if (poiLL.GetLon() > regions[0] || poiLL.GetLat() > regions[1]
                    || poiLL.GetLon() < regions[2] || poiLL.GetLat() < regions[3]) {

            } else {
                Point ff = LL2XY(poiLL, mapView);
                paint.setColor(Color.parseColor("#AAAF0000"));
                canvas.drawCircle(ff.x, ff.y, Utils.dip2px(context, 12), paint);
                String strPrn = "S";
                float textWidth = paint.measureText(strPrn) / 2;
                float textHeight = paint.getTextSize() / 2;
                paint.setColor(Color.WHITE);
                canvas.drawText(strPrn, ff.x - textWidth, ff.y + textHeight - 1,
                        paint);
            }
        }
    }

    Point LL2XY(LonLat ll, MapView mapView) {
        Point A = new Point();
        Point B = new Point();
        Projection pj = mapView.getProjection();
        pj.toProjectedPixels(ll.GetLat(), ll.GetLon(), A);
        pj.toPixelsFromProjected(A, B);
        return B;
    }

    public void drawmeasureRT3(Context context, Canvas canvas, org.mapsforge.core.model.BoundingBox bb, byte zoomLevel, org.mapsforge.core.model.Point topLeftPoint, DisplayModel displayModel) {
        if (measureRT == null
                || measureRT.measurePtList == null
                || measureRT.measurePtList.size() < 2) {
            return;
        }

        int w = canvas.getWidth();
        int h = canvas.getHeight();

        double[] regions = {bb.maxLongitude, bb.maxLatitude, bb.minLongitude, bb.minLatitude};

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(6);
        paint.setAntiAlias(true);
        PathEffect pathEffect = new DashPathEffect(new float[]{5, 0}, 0);
        paint.setPathEffect(pathEffect);
        paint.setColor(Color.parseColor("#AAFF0000"));

        long mapSize = MercatorProjection.getMapSize(zoomLevel, displayModel.getTileSize());
        int count = measureRT.measurePtList.size();

        List<GeoPoint> points = new ArrayList<>();
        android.graphics.Path path = new android.graphics.Path();
        for (int i = 0; i < count; i++) {
            LonLat poiLL = measureRT.measurePtList.get(i).getLL();
            points.add(new GeoPoint(poiLL.GetLat(), poiLL.GetLon()));

            float x = (float) (MercatorProjection.longitudeToPixelX(poiLL.GetLon(), mapSize) - topLeftPoint.x);
            float y = (float) (MercatorProjection.latitudeToPixelY(poiLL.GetLat(), mapSize) - topLeftPoint.y);

            if (i == 0) {
                path.moveTo(x, y);
            } else {
                path.lineTo(x, y);
            }
        }
        canvas.drawPath(path, paint);

        //画起点
        if (count > 0) {
            paint.setStyle(Paint.Style.FILL);
            paint.setTextSize(13);
            LonLat poiLL = measureRT.measurePtList.get(0).getLL();

            if (poiLL.GetLon() > regions[0] || poiLL.GetLat() > regions[1]
                    || poiLL.GetLon() < regions[2] || poiLL.GetLat() < regions[3]) {

            } else {
                int x = (int) (MercatorProjection.longitudeToPixelX(poiLL.GetLon(), mapSize) - topLeftPoint.x);
                int y = (int) (MercatorProjection.latitudeToPixelY(poiLL.GetLat(), mapSize) - topLeftPoint.y);
                Point ff = new Point(x, y);
                paint.setColor(Color.parseColor("#AAAF0000"));
                canvas.drawCircle(ff.x, ff.y, Utils.dip2px(context, 12), paint);
                String strPrn = "S";
                float textWidth = paint.measureText(strPrn) / 2;
                float textHeight = paint.getTextSize() / 2;
                paint.setColor(Color.WHITE);
                canvas.drawText(strPrn, (int) (ff.x - textWidth), (int) (ff.y + textHeight - 1),
                        paint);
            }
        }
    }

}
